/***************************************************************************
 * Copyright (C) 2023-, openlinyou, <linyouhappy@outlook.com>
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 ***************************************************************************/

#ifndef HEADER_OPEN_COM_HTTP_CLIENT_H
#define HEADER_OPEN_COM_HTTP_CLIENT_H

#include <vector>
#include <set>
#include <string.h>
#include <unordered_map>
#include "openserver.h"
#include "openhttps.h"
#include "openssl.h"

namespace open
{

////////////OpenHttpClientMsg//////////////////////
struct OpenHttpClientMsg : public OpenMsgProtoMsg
{
    int type_;
    std::shared_ptr<OpenHttpRequest> request_;

    static inline int MsgType() { return 0; }
    OpenHttpClientMsg() :OpenMsgProtoMsg(), type_(MsgType()) {}
    static inline int MsgId() { return (int)(int64_t)(void*)&MsgId; }
    virtual inline int msgId() const { return OpenHttpClientMsg::MsgId(); }
};

////////////OpenHttpClientSyncMsg//////////////////////
struct OpenHttpClientSyncMsg : public OpenHttpClientMsg
{
    OpenSync openSync_;
    static inline int MsgType() { return 1; }
    OpenHttpClientSyncMsg() :OpenHttpClientMsg() { type_ = MsgType(); }
};

////////////OpenHttpClientStreamMsg//////////////////////
struct OpenHttpClientStreamMsg : public OpenHttpClientMsg
{
    int pid_;
    int fd_;
    uint64_t uid_;
    static inline int MsgType() { return 2; }
    OpenHttpClientStreamMsg() :OpenHttpClientMsg(), pid_(-1), fd_(-1), uid_(-1) { type_ = MsgType(); }
};

////////////OpenHttpClientStreamNoticeMsg//////////////////////
struct OpenHttpClientStreamNoticeMsg : public OpenMsgProtoMsg
{
    int type_;
    int reqPid_;
    int reqFd_;
    int pid_;
    int fd_;
    uint64_t uid_;
    OpenBuffer buffer_;
    OpenHttpClientStreamNoticeMsg() : OpenMsgProtoMsg(), reqPid_(-1), reqFd_(-1), pid_(-1), fd_(-1), uid_(-1), type_(0) {}
    static inline int MsgId() { return (int)(int64_t)(void*)&MsgId; }
    virtual inline int msgId() const { return OpenHttpClientStreamNoticeMsg::MsgId(); }
};

////////////OpenComHttpClient//////////////////////
class OpenComHttpClient : public OpenComSocket
{
    struct Client
    {
        int fd_;
        int pid_;
        OpenComHttpClient* com_;

        bool isClosed_;
        TlsContext* tls_;
        SslCtx* sslCtx_;
        TlsBuffer buffer_;
        std::shared_ptr<OpenHttpClientMsg> clientMsg_;
        OpenHttpClientStreamMsg* streamMsg_;

        bool isOpenCache_;
        bool isCreateSendFile_;
        OpenWriteFile cacheSendFile_;
        bool isCreateReceiveFile_;
        OpenWriteFile cacheReceiveFile_;

        Client();
        ~Client();
        bool start(std::shared_ptr<OpenHttpClientMsg>& clientMsg);
        void sendRequest();
        void sendRawBuffer();
        void sendBuffer();
        void open();
        void update(const char* data, size_t size);
        void onOpen();
        void onData(const char* data, size_t size);
        void close();
    };
    std::unordered_map<int, Client> mapFdToClient_;

    virtual void onSocketData(const OpenSocketMsg& msg);
    virtual void onSocketClose(const OpenSocketMsg& msg);
    virtual void onSocketOpen(const OpenSocketMsg& msg);
    virtual void onSocketError(const OpenSocketMsg& msg);
    virtual void onSocketWarning(const OpenSocketMsg& msg);

    SslCtx sslCtx_;
public:
    OpenComHttpClient() :OpenComSocket(), sslCtx_(false) {}

    virtual ~OpenComHttpClient();
    virtual bool start(OpenServer* worker);
    void onOpenMsgProto(OpenMsgProto& proto);
    virtual inline OpenCom* newCom() { return new OpenComHttpClient; }
};


};


#endif   //HEADER_OPEN_COM_HTTP_CLIENT_H
